﻿using Basic.RPC.Abstract;
using BeetleX.XRPC.Clients;
using BeetleX.XRPC.Packets;

namespace Basic.RPC.Impl;

/// <summary>
/// XRpc客户端
/// </summary>
internal class BeetleXRpcClient : IRpcClient
{
    private List<RpcClientService> RpcInfos;
    private List<XRPCClient> Clients;

    private IDictionary<string, IDictionary<string, string>> ServiceDict;

    public BeetleXRpcClient(List<RpcClientService> rpcInfo, IDictionary<string, IDictionary<string, string>> serviceDict)
    {
        RpcInfos = rpcInfo;
        ServiceDict = serviceDict;
        Clients = new List<XRPCClient>();
    }

    ~BeetleXRpcClient()
    {
        Dispose();
    }

    public T GetService<T>() where T : class
    {
        Type type = typeof(T);
        Guid typeId = type.GUID;
        RpcClientService info = RpcInfos.Where(s => s.InterfaceTypes.Any(t => t.GUID == typeId)).FirstOrDefault();
        if (info != null)
        {
            var kv = ServiceDict.Where(s => s.Value.Where(k => k.Value == info.ServiceName).Any()).FirstOrDefault();
            if (kv.Key != null)
            {
                var meta = kv.Value;
                if (meta.TryGetValue("IP", out string ip) && meta.TryGetValue("RpcPort", out string portStr) && int.TryParse(portStr, out int port))
                {
                    XRPCClient client = Clients.Where(s => s.Host == ip && s.Port == port).FirstOrDefault();
                    if (client == null)
                    {
                        client = new XRPCClient(ip, port);
                        client.Options.ParameterFormater = new JsonPacket();
                        Clients.Add(client);
                    }
                    return client.Create<T>();
                }
            }
        }
        return null;
    }

    #region Dispose

    private bool disposedValue;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                if (Clients.Count > 0)
                {
                    foreach (var item in Clients)
                    {
                        item?.Dispose();
                    }
                }
            }
            // TODO: 释放未托管的资源(未托管的对象)并重写终结器
            // TODO: 将大型字段设置为 null
            disposedValue = true;
        }
    }

    public void Dispose()
    {
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }
    #endregion

}